package com.ilink.groundservice.controller;


import static com.ilink.groundservice.entity.PO.innovationPlaza.InnovationPlaza.ProjectType.Competition;
import com.ilink.ilinkcommon.log.method.MethodLog;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.ilink.groundservice.entity.PO.innovationPlaza.CompetitionMetadata;
import com.ilink.groundservice.entity.PO.innovationPlaza.InnovationConnectTags;
import com.ilink.groundservice.entity.PO.innovationPlaza.InnovationPlaza;
import com.ilink.groundservice.entity.PO.innovationPlaza.InnovationTags;
import com.ilink.groundservice.entity.VO.innovationPlaza.CompetitionResponse;
import com.ilink.groundservice.mapper.innovationPlaza.CompetitionMapper;
import com.ilink.groundservice.mapper.innovationPlaza.InnovationConnectTagsMapper;
import com.ilink.groundservice.mapper.innovationPlaza.InnovationPlazaMapper;
import com.ilink.groundservice.mapper.innovationPlaza.InnovationTagsMapper;
import com.ilink.groundservice.service.InnovationPlaza.CompetitionService;
import com.ilink.ilinkcommon.domain.R;
import com.ilink.ilinkcommon.service.oss.OssService;
import com.ilink.ilinkcommon.utils.SnowflakeIdGenerator;
import com.ilink.ilinkcommon.utils.UserContext;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

@RestController
@RequestMapping("/ground/innovationPlaza/competition")
public class CompetitionController {

    @Autowired
    private CompetitionService competitionService;

    @Autowired
    private OssService ossService;

    @Autowired
    private CompetitionMapper competitionMapper;

    @Autowired
    private InnovationTagsMapper innovationTagsMapper;

    @Autowired
    private InnovationPlazaMapper innovationPlazaMapper;

    @Autowired
    private InnovationConnectTagsMapper innovationConnectTagsMapper;

    /**
     * @return 最常使用的8个标签(List < InnovationTags > 形式)
     * @author dzy
     */
    @MethodLog(value = "获取最常使用的8个赛事标签")
    @GetMapping("/getCommonCompetitionTags")
    public R getCommonDatasetTags() {
        try {
            return R.ok(competitionService.getCommonTags());
        } catch (Exception e) {
            return R.error("内部服务器错误：" + e);
        }
    }

    // 条件分页查询赛事信息
    @MethodLog(value = "条件分页查询赛事信息")
    @GetMapping("/getAllCompetitions")
    public R getAllCompetitions(
            @RequestParam(required = false, defaultValue = "") String sentence,
            @RequestParam(required = false, defaultValue = "") List<String> tags,
            @RequestParam(required = false, defaultValue = "publisher_time") String sortBy,
            @RequestParam(defaultValue = "1") int pageNum,
            @RequestParam(required = false, defaultValue = "10") int pageSize
    ) {
        try {
            IPage<CompetitionResponse> competitionsPage = competitionService.getAllCompetitionsEnd(sentence, tags, sortBy, pageNum, pageSize);
            if (competitionsPage != null) {
                return R.ok("查询到赛事信息数据", competitionsPage);
            } else {
                return R.error("未查询到赛事信息数据");
            }
        } catch (Exception e) {
            return R.error("未查询到赛事信息数据，由于" + e.getMessage());
        }

    }

    // 赛事点赞:加一个状态 已经修改为收藏
    @MethodLog(value = "赛事收藏或取消收藏操作")
    @PostMapping("/toggleLike")
    public R toggleLike(@RequestParam Long projectId) {
        try {
            String userId = UserContext.getUserId();
            String result = competitionService.toggleLike(projectId, userId);
            return R.ok(result);
        } catch (Exception e) {
            return R.error(e.getMessage());

        }

    }

    // 赛事分享
    @MethodLog(value = "赛事分享操作")
    @PostMapping("/shareProject")
    public R shareProject(@RequestParam Long projectId) {
        boolean isSuccess = competitionService.incrementShareNum(projectId);
        if (isSuccess) {
            return R.ok("分享量+1");
        } else {
            return R.error("赛事分享失败");
        }
    }

    // 赛事浏览
    @MethodLog(value = "赛事浏览操作")
    @PostMapping("/clickProject")
    public R clickProject(@RequestParam Long projectId) {
        boolean isSuccess = competitionService.incrementLookNum(projectId);
        if (isSuccess) {
            return R.ok("点击量+1");
        } else {
            return R.error("赛事浏览失败");
        }
    }

    // 获取赛事公告详情
    @MethodLog(value = "获取赛事公告详情")
    @GetMapping("/getAnnouncementById")
    public R getAnnouncementInfoById(@RequestParam Long competitionId) {
        try {
            String userId = UserContext.getUserId();
            return R.ok(competitionService.getAnnouncementInfoById(competitionId, userId));
        } catch (Exception e) {
            return R.error(e.getMessage());
        }
    }

    // 上传赛事公告文档到OSS
    @MethodLog(value = "上传赛事公告文档到OSS")
    @PostMapping("/uploadAnnouncementOSS")
    public R uploadAnnouncement(
            @RequestParam("file") MultipartFile file,
            @RequestParam("projectId") BigInteger projectId
    ) {
        String originalFilename = file.getOriginalFilename();
        String fileExtension = "";
        if (originalFilename != null && originalFilename.contains(".")) {
            fileExtension = originalFilename.substring(originalFilename.lastIndexOf("."));
        } else {
            return R.error("文件解析扩展名出现错误：" + originalFilename);
        }
        String newFilename = projectId + fileExtension;
        String filePath = "大创广场/赛事中心/";
        if (ossService.uploadFile(file, filePath, newFilename)) {
            CompetitionMetadata competitionMetadata = competitionMapper.selectById(projectId);
            competitionMetadata.setTextPath(filePath + newFilename);
            competitionMapper.updateById(competitionMetadata);
            return R.ok("赛事文档导入成功，OSS文件上传成功: " + file.getOriginalFilename());
        } else {
            return R.error("OSS文件上传失败: " + file.getOriginalFilename());
        }
    }

    // 外部导入赛事数据
    @Transactional
    @MethodLog(value = "外部导入赛事数据操作")
    @PostMapping("/uploadCompetition")
    public R uploadCompetition(
            @RequestParam("file") MultipartFile file,
            @RequestPart("Competition") CompetitionMetadata competitionMetadata,
            @RequestParam("tags") List<String> tags,
            @RequestParam("CompetitionLink") String CompetitionLink,
            @RequestParam("CompetitionOfficialLink") String CompetitionOfficialLink
    ) {
        try {
            String originalFilename = file.getOriginalFilename();
            String fileExtension = "";
            if (originalFilename != null && originalFilename.contains(".")) {
                fileExtension = originalFilename.substring(originalFilename.lastIndexOf("."));
            } else {
                return R.error("文件解析扩展名出现错误：" + originalFilename);
            }
            SnowflakeIdGenerator idGenerator = new SnowflakeIdGenerator(2, 2);
            Long projectId = idGenerator.nextId();
            InnovationPlaza innovationPlaza = new InnovationPlaza();
            innovationPlaza.setProjectId(projectId);
            innovationPlaza.setProjectType("Competition");
            innovationPlazaMapper.insert(innovationPlaza);
            competitionMetadata.setCompetitionId(projectId);
            competitionMetadata.setCompetitionLink(CompetitionLink);
            competitionMetadata.setCompetitionOfficialLink(CompetitionOfficialLink);
            for (String tag : tags) {
                if (innovationTagsMapper.checkTagExists("Competition", tag) == 0) {
                    InnovationTags newtag = new InnovationTags();
                    newtag.setName(tag);
                    newtag.setTagType("Competition");
                    innovationTagsMapper.insert(newtag);
                }
                InnovationTags newtag = innovationTagsMapper.selectOne(
                        new QueryWrapper<InnovationTags>().eq("name", tag)
                                .eq("tag_type", "Competition"));
                InnovationConnectTags connectTags = new InnovationConnectTags();
                connectTags.setProjectId(projectId);
                connectTags.setTagId(newtag.getTagId());
                innovationConnectTagsMapper.insert(connectTags);
            }
            String newFilename = projectId + fileExtension;
            String filePath = "大创广场/赛事中心/";
            if (ossService.uploadFile(file, filePath, newFilename)) {
                competitionMetadata.setTextPath(filePath + newFilename);
                competitionMapper.insert(competitionMetadata);
                return R.ok("赛事文档导入成功，OSS文件上传成功: " + file.getOriginalFilename(), competitionMetadata);
            } else {
                return R.error("OSS文件上传失败: " + file.getOriginalFilename(), competitionMetadata);
            }
        } catch (Exception e) {
            return R.error("赛事上传出现异常: " + e.getMessage());
        }
    }

    // 获取赛事公告文档链接
    @MethodLog(value = "获取赛事公告文档OSS链接")
    @GetMapping("/getAnnouncementOSS")
    public R getAnnouncementOSS(@RequestParam Long projectId) {
        try {
            CompetitionMetadata competitionMetadata = competitionMapper.selectById(projectId);
            if (competitionMetadata == null) {
                return R.error("赛事ID有误，该赛事不存在");
            } else if (competitionMetadata.getTextPath() == null) {
                return R.error("赛事文档不存在");
            } else {
                return R.ok("成功返回赛事文档OSS链接", ossService.getFileUrl(competitionMetadata.getTextPath()));
            }
        } catch (Exception e) {
            return R.error(e.getMessage());
        }
    }

    // 获取赛事公告原文链接
    @MethodLog(value = "获取赛事公告原文链接")
    @GetMapping("/getAnnouncementLink")
    public R getAnnouncementLink(@RequestParam Long projectId) {
        CompetitionMetadata competitionMetadata = competitionMapper.selectById(projectId);
        if (competitionMetadata != null) {
            String link = competitionMetadata.getCompetitionLink();
            if (link == null) {
                return R.error("该赛事没有提供原文链接");
            } else {
                return R.ok("成功返回原文链接", link);
            }
        } else {
            return R.error("赛事ID有误，该赛事不存在");
        }
    }

    // 获取赛事公告文件并通过后端代理访问
    @MethodLog(value = "通过后端代理获取赛事公告文件")
    @GetMapping("/getAnnouncement")
    public ResponseEntity<Object> getAnnouncement(@RequestParam Long projectId) {
        CompetitionMetadata competitionMetadata = competitionMapper.selectById(projectId);
        if (competitionMetadata != null) {
            String link = competitionMetadata.getCompetitionLink();
            if (link == null) {
                return ResponseEntity.badRequest().body("该赛事没有提供原文链接");
            } else {
                return competitionService.getFileFromLink(link);
            }
        } else {
            return ResponseEntity.badRequest().body("赛事ID有误，该赛事不存在");
        }
    }

    // 下载赛事公告文件
    @MethodLog(value = "下载赛事公告文件")
    @GetMapping("/getAnnouncementfile")
    public R getAnnouncementfile(@RequestParam Long projectId) {
        try {
            CompetitionMetadata competitionMetadata = competitionMapper.selectById(projectId);
            if (competitionMetadata == null) {
                return R.error("赛事ID有误，该赛事不存在");
            } else if (competitionMetadata.getTextPath() == null) {
                return R.error("赛事文档不存在");
            } else {
                File file = competitionService.downloadFileFromUrl(ossService.getFileUrl(competitionMetadata.getTextPath()));
                InputStreamResource resource = new InputStreamResource(new FileInputStream(file));
                HttpHeaders headers = new HttpHeaders();
                headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + file.getName());
                headers.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_OCTET_STREAM_VALUE);
                Map<String, Object> responseMap = new HashMap<>();
                responseMap.put("file", file);
                responseMap.put("resource", resource);
                responseMap.put("headers", headers);
                return R.ok(responseMap);
            }
        } catch (IOException ex) {
            return R.error(ex.getMessage());
        }
    }
}
